classdef eyetrack_PBT < eyetrackexp
    
    
    properties
        scn_pointer
    end
    
    methods
        function self = eyetrack_PBT()
            % Restart the seed of the random function
            self = self@eyetrackexp();
            % Overrides the variable scn
            self.scn  = struct('mon',max(Screen('Screens')), ... % Only one monitor
                'w',1600, ... % 1 = 640x480; 3 = 1024x768
                'h',1200, ...
                'color',32, ... Color is 32 bits
                'refresh_rate',60,...
                'wcm',40.8); % Refresh rate in Hz
            self.stim       = struct('size',15,'rgb',[255 255 255]);
            
        end
        
        function start_GM(self)
            % Initializes the graphical motor, i.e., cogent or PTB.
            if self.Eyelink
                Eyelink('Initialize');
            end
            % Initiliazies the screen an saves the pointer into scn_pointer
            [self.scn_pointer]=Screen('OpenWindow',self.scn.mon,0,...
                [0 0 self.scn.w self.scn.h], self.scn.color);
            % Draws a black screen
            HideCursor();
            black=BlackIndex(self.scn_pointer);
            Screen('FillRect',self.scn_pointer,black);
            Screen(self.scn_pointer, 'Flip');
            % Saves the refresh rate
            self.scn.refresh_rate=Screen('GetFlipInterval', self.scn_pointer);
            % Wait to have any input key pressed
            self.centeredText('Press a key when ready...');
            FlushEvents();
            while 1
                avail = CharAvail();
                if avail; break; end
            end
        end
        
        function centeredText(self,text)
            % Wait to have any input key pressed
            textrect = Screen('TextBounds', self.scn_pointer, text);
            [xoffset, yoffset] = RectCenter(textrect);
            Screen(self.scn_pointer, 'DrawText', text,...
                self.scn.w/2-xoffset,self.scn.h/2-yoffset,[255,255,255]);
            Screen(self.scn_pointer, 'Flip');
        end
        
        function runScreen(self)
            
            % Start dialog
            self.startDialog()
            % Preamble
            self.start_GM()
            function [goout,kn]= escapeTrial()
                goout = 0; kn = 0; avail = CharAvail();
                if avail
                    FlushEvents();
                    centeredText(self,['Press ''q'' to quit.' ...
                        ' Press any other key to continue. '])
                    while 1
                       avail = CharAvail();
                       if avail; break; end
                    end
                    k = GetChar();
                    if k == 'q'
                        goout = 1; kn = 1;
                    end
                end
                FlushEvents();
            end
            function checkOccluder()
                % No eye link
                if self.Eyelink == 0; return; end
                if self.occluder.Xbase(b,t) > 3   % i.e. if occ overhangs
                    if self.occluder.X(b,t) < cx
                        %Eyelink('Message', 'OCCLUDER');
                    end
                else
                    if self.occluder.X(b,t) < cx < self.occluder.End(b,t)
                        %Eyelink('Message', 'OCCLUDER');
                    end
                end
            end
            % This is a small and silly hack
            indexes = reshape(1:self.num_blocks * self.num_trials,...
                self.num_blocks,self.num_trials)';
            
            stimulusPosition = ...
                inline('[ cx - size,self.scn.h/2 - size,cx + size,self.scn.h/2 + size]', ...
                'self','cx','size');
            FlushEvents();
            for trial = indexes(:)' 
                [b,t]= ind2sub([self.num_blocks,self.num_trials],trial);
                if self.Eyelink;
                   try
                    calibrateEyetracker(self.scn_pointer,self.scn.mon);
                    FlushEvents();
                   end
                end
                % Draws the fixation!!
                cx = (self.randomFixation(trial)*(self.scn.w/2)) + (self.scn.w/2);
                stim_position = stimulusPosition(self,cx,self.stim.size);
                Screen('FillOval',self.scn_pointer,self.stim.rgb,round(stim_position))
                stim_position = stimulusPosition(self,cx,self.stim.size/3);
                Screen('FillOval',self.scn_pointer,[1,1,1],round(stim_position));
                Screen(self.scn_pointer, 'Flip');
                % Brief stop
                tic;while toc < self.fix.time/2;end
                % Send parameters
                if self.Eyelink
                    display('start')
                    Eyelink('Openfile', ['s' num2str(self.Epar.Sbj) 'e' ...
                        num2str(self.Epar.Exp) 'b' num2str(b) ...
                        't' num2str(t) '.edf']);        % open a file on the eyetracker
                    Eyelink('StartRecording');
                    self.sendparameters(trial);
                end
                % Brief stop
                tic;while toc < self.fix.time/2;end
                if self.Eyelink;
                    Eyelink ('Message', 'START');
                end
                c = 1;
                dt = 0;
                % LeTteRBox convention Left - Top - Right - Bottom
                % The sign(self.randomFixation(trial)) is used to put the
                % stimuli in contralateral position from the starting
                % position.
                occluderPosition = [...
                    self.scn.w/2 + self.occluder.X(trial) - self.occluder.W(trial)/2, ...
                    self.occluder.y + self.scn.h/2 - self.occluder.h/2,...
                    self.scn.w/2 + self.occluder.X(trial) + self.occluder.W(trial)/2, ...
                    self.occluder.y + self.scn.h/2 + self.occluder.h/2,...
                    ];
                while dt <= self.cycles
                    dt = dt+(1/self.FpC(trial));
                    if c && abs(dt - self.jump.frame(trial)) <= 2/self.FpC(trial)
                        dt = dt + self.jump.m(trial);
                        c = 0;
                    end
                    cx = self.stimuli(dt*2*pi)* self.randomFixation(trial)*self.scn.w/2 + self.scn.w/2;
                    % LeTteRBox convention Left - Top - Right - Bottom
                    stim_position = stimulusPosition(self,cx,self.stim.size);
                    Screen('FillOval',self.scn_pointer,self.stim.rgb,stim_position)
                    % Draws a point in the middle
                    stim_position = stimulusPosition(self,cx,self.stim.size/3);
                    Screen('FillOval',self.scn_pointer,[1,1,1],stim_position)
                    % Draw occluder
                    Screen('FillRect',self.scn_pointer,self.occluder.rgb, occluderPosition);
                    Screen(self.scn_pointer, 'Flip');
                    checkOccluder();
                    [goout,kn] = escapeTrial();
                    if goout; break; end
                end
                % Notify end of the recording
                if self.Eyelink
                    Eyelink ('Message', 'END');
                end
                % If it breaks it trashes all the information
                if kn; break; end 
                % Transtion between trials
                self.trialTransition(trial);
                % Pauses the script and restarts it
                if ~mod(t,self.pauses)
                    % Pause message
                    self.centeredText('Pause');
                    tic;while toc < 1;end
                    % Shuts down and wait for something to happen
                    Screen('CloseAll');
                    if self.Eyelink; Eyelink('Shutdown'); end
                    % A horrible hack... I don't know how to properly flush
                    % the command line from what has been going on during
                    % the whole trial...
                    fprintf(1,'Please wait\n');
                    tic; while toc < 30;end
                    self.start_GM() % Initializes every thing again
                end
                FlushEvents();
            end
            if self.Eyelink; Eyelink('Shutdown'); end
            % Shutdown screen
            Screen('CloseAll');
        end
        function trialTransition(self,trial)
            % What is done between trials
            stimulusPosition = ...
                inline('[ cx - size,self.scn.h/2 - size,cx + size,self.scn.h/2 + size]', ...
                'self','cx','size');
            cx = (self.randomFixation(trial)*(self.scn.w/2)) + (self.scn.w/2);
            stim_position = stimulusPosition(self,cx,self.stim.size);
            Screen('FillOval',self.scn_pointer,self.stim.rgb,round(stim_position))
            stim_position = stimulusPosition(self,cx,self.stim.size/3);
            Screen('FillOval',self.scn_pointer,[1,1,1],round(stim_position));
            Screen(self.scn_pointer, 'Flip');
            tic;while toc < self.fix.time;end
            % Saves file
            if self.Eyelink
                Eyelink('Closefile');
                Eyelink('ReceiveFile');
            end
            Screen('FillRect',self.scn_pointer,[1,1,1]);
            Screen(self.scn_pointer, 'Flip');
            tic;while toc < self.fix.time*2;end
        end
    end
end